/**
 * 
 */
package com.module.bp.event.base;

import java.util.ArrayList;
import java.util.Iterator;

import com.dalonedrau.d20.Diceroller;
import com.dalonedrau.jogl.engine.GameApplet;
import com.dalonedrau.jogl.engine.Interface;
import com.dalonedrau.pool.PooledStringBuilder;
import com.dalonedrau.pool.StringBuilderPool;
import com.module.bp.bus.BPHexMap;
import com.module.bp.bus.graph.BreadthFirstSearch;
import com.module.bp.engine.BPController;
import com.module.bp.engine.Turn;
import com.module.bp.player.BPConsts;
import com.module.bp.player.BPParty;

/**
 * @author Donald
 */
public final class LandTravelEvent extends BaseEvent {
	/** the travel destination. */
	private Integer	destination;
	private boolean	isRiverCrossing	= false;
	/** the travel source. */
	private Integer	source;
	/**
	 * Creates a new instance of {@link LandTravelEvent}.
	 * @param from the travel departure
	 * @param to the travel destination
	 */
	public LandTravelEvent(final int from, final int to) {
		destination = to;
		source = from;
	}
	/**
	 * {@inheritDoc}
	 */
	@Override
	public void fire() throws Exception {
		if (destination == null || source == null) {
			throw new Exception("Travel destination cannot be null!");
		}
		super.setFired(true);
		if (super.happens()) {
			// calculate move
			BreadthFirstSearch bfs =
					new BreadthFirstSearch(
							BPController.getInstance().getOverworldGraph(),
							source);
			Iterator<Integer> iter = bfs.pathTo(destination).iterator();
			ArrayList<Integer> list = new ArrayList<Integer>();
			while (iter.hasNext()) {
				int n = iter.next();
				System.out.println(n);
				System.out.println(
						BPHexMap.getInstance().getHexVector(n));
				list.add(n);
			}
			if (list.size() > 2) {
				// does the party have a raft?
				if (BPParty.getInstance().hasRaft()) {
					System.out.println("Can travel");
				} else {
					isRiverCrossing = true;
					PooledStringBuilder sb =
							StringBuilderPool.getInstance().getStringBuilder();
					sb.append("You will need to cross the ");
					sb.append(BPHexMap.getInstance().getRiverName(list.get(1)));
					sb.append(" to get to that area.  In order to do so, you ");
					sb.append("will first need to find a place to ford the ");
					sb.append("river or materials to construct a raft.  Do  ");
					sb.append("you want to try to go across?");
					Interface.getInstance().showSmallOptionsMessageWindow(
							"River Crossing", sb.toString(), this);
					sb.returnToPool();
				}
			} else {
				super.setResolved(true);
				try {
					// if party has possible guide, display unit picker to
					// assign guide

					// if no guide, check to see if party gets lost

					// if not lost, reduce party's moves available
					// and start move animation
					startTravelAction(false);
				} catch (Exception ex) {
					JOGLErrorHandler.getInstance().fatalError(ex);
				}
			}
			// was move success?
			// move party all the way

			// was move a failure?
			// move party in circle

			// was there an encounter?
			// move 1/2 then resolve encounter
		} else {
			super.setResolved(true);
		}
	}
	/**
	 * Determines the party gets lost when traveling over land or airborne.
	 * @return true if the party gets lost; false otherwise
	 */
	private boolean getsLost() {
		boolean lost = false;
		// check if travel is across road
		Iterator<Integer> iter =
				BPController.getInstance().getOverworldGraph()
						.getImmediateRoadAdjacencies(source).iterator();
		boolean roadTravel = false;
		while (iter.hasNext()) {
			if (iter.next().intValue() == destination.intValue()) {
				roadTravel = true;
				break;
			}
		}
		iter = null;
		// party cannot get lost travelling by road
		if (!roadTravel) {
			// check if party gets lost
			// roll 2d6
			int roll = Diceroller.getInstance().rollXdY(2, BPConsts.DIE_ROLL);
			// check to see if party has a guide
			boolean hasGuide = false;
			// if party has guide assigned, subtract 1 from dice roll
			if (hasGuide) {
				roll--;
			}
			if (isRiverCrossing) {
				if (roll >= 8) {
					lost = true;
				}
			} else if (BPParty.getInstance().canTravelFlying()) {
				if (roll >= 12) {
					lost = true;
				}
			} else {
				// check roll against terrain type party is leaving
				int type = BPHexMap.getInstance().getHexType(source);
				switch (type) {
				case BPConsts.HEX_FARM:
				case BPConsts.HEX_TOWN_FARM:
					if (roll >= 10) {
						lost = true;
					}
					break;
				case BPConsts.HEX_COUNTRY:
				case BPConsts.HEX_TEMPLE_COUNTRY:
				case BPConsts.HEX_TOWN_COUNTRY:
					if (roll >= 9) {
						lost = true;
					}
					break;
				case BPConsts.HEX_FOREST:
				case BPConsts.HEX_TEMPLE_FOREST:
					if (roll >= 8) {
						lost = true;
					}
					break;
				case BPConsts.HEX_HILLS:
				case BPConsts.HEX_RUINS_HILLS:
					if (roll >= 8) {
						lost = true;
					}
					break;
				case BPConsts.HEX_MOUNTAINS:
				case BPConsts.HEX_RUINS_MOUNTAINS:
				case BPConsts.HEX_TEMPLE_MOUNTAINS:
					if (roll >= 7) {
						lost = true;
					}
					break;
				case BPConsts.HEX_SWAMP:
					if (roll >= 5) {
						lost = true;
					}
					break;
				case BPConsts.HEX_DESERT_NO_OASIS:
				case BPConsts.HEX_DESERT_OASIS:
				case BPConsts.HEX_RUINS_DESERT_OASIS:
				case BPConsts.HEX_TEMPLE_DESERT:
					if (roll >= 6) {
						lost = true;
					}
					break;
				default:
					PooledStringBuilder sb =
							StringBuilderPool.getInstance().getStringBuilder();
					sb.append("Hex ");
					sb.append(source);
					sb.append(" set to invalid type: ");
					sb.append(type);
					Exception ex = new Exception(sb.toString());
					sb.returnToPool();
					JOGLErrorHandler.getInstance().fatalError(ex);
					break;
				}
			}
		}
		return lost;
	}
	/** 
	 * Start the travel action.
	 * @param lost flag indicating whether the party gets lost.
	 * @throws Exception if an error occurs
	 */
	private void startTravelAction(final boolean lost) throws Exception {
		// REDUCE PARTY'S MOVES
		if (lost) {
			// REMOVE ALL MOVES
			BPParty.getInstance().setNumMovesTaken(
					BPParty.getInstance().getNumMovesPossible());
		} else {
			// REMOVE ONE MOVE
			BPParty.getInstance().setNumMovesTaken(
					BPParty.getInstance().getNumMovesTaken() + 1);
		}
		if (Turn.getInstance().getCurrentPhase() == Turn.PHASE_ACTION) {
		// START MOVEMENT IN NEXT PHASE
		Turn.getInstance().addEvent(Turn.getInstance().getNextPhase(),
				new MapLandAnimationEvent(source, destination, lost));
		// END THE CURRENT PHASE
		Turn.getInstance().addEvent(new EndPhaseEvent());
		} else {
			// START MOVEMENT IN THIS PHASE
			Turn.getInstance().addEventAfterId(super.getId(),
					new MapLandAnimationEvent(source, destination, lost));
			
		}
	}
	/**
	 * {@inheritDoc}
	 */
	@Override
	public void setUserInput(final boolean response) {
		if (response) {
			System.out.println("got response true");
			// move was paused due to user input required. continue to move
			// the party
			super.setResolved(true);
			try {
				// if party has possible guide, display unit picker to assign
				// guide

				// check for lost

				// START MOVE
				startTravelAction(false);
				// if party has possible guide, display unit picker to assign
				// guide
			} catch (Exception ex) {
				JOGLErrorHandler.getInstance().fatalError(ex);
			}
		} else {
			// cancel move
			// player hasn't moved, map still shows selections,
			// continue as you were
		}
	}
	/**
	 * {@inheritDoc}
	 */
	@Override
	public void setUserInput(int input) {
		// set the guide selected
	}
}
